#include <iostream>
#include <string>
#include <list>
#include <memory>
#include <algorithm>
#include <sys/types.h>
#include <sys/socket.h>

#include "InetAddr.hpp"
#include "Log.hpp"
#include "Mutex.hpp"

using namespace LogModule;
using namespace LockModule;

//观察者模式
//观察者模式（Observer Pattern）是一种常用的设计模式，属于行为型设计模式。它定义了对象间的一种一对多的依赖关系
//，使得当一个对象（称为“主题”或“被观察者”）改变状态时，所有依赖于它的对象（称为“观察者”）都会自动得到通知并被自动更新。
class UserInterface
{
public:
    virtual ~UserInterface() = default;
    virtual void SendTo(int sockfd, const std::string &message) = 0;
    virtual bool operator==(const InetAddr &u) = 0;
    virtual std::string Id() = 0;
};
class User : public UserInterface
{
public:
    User(const InetAddr& id):_id(id)
    {

    }
    void SendTo(int sockfd, const std::string &message) override
    {
        LOG(LogLevel::DEBUG) << "send message to " << _id.Addr() << " info: " << message;
        int n = ::sendto(sockfd,message.c_str(),message.size(),0,_id.NetAddr(),_id.NetAddrLen());
        if(n == -1)        {
            LOG(LogLevel::FATAL) << "send fail";
            Die(2);
        }
    }
    bool operator==(const InetAddr &u) override
    {
        return _id == u;
    }
    std::string Id() override { return _id.Addr(); };

    ~User(){}
private:
    InetAddr _id;
};

class UserManage
{
public:
    UserManage(){}
    void AddUser(InetAddr& id) 
    {
        LockGuard lck(_mutex);
        for(auto& user : _online_user)
        {
            if(*user == id)
            {
                LOG(LogLevel::INFO) << id.Addr() << "用户已经存在";
                return;
            }
        }
        LOG(LogLevel::INFO) << " 新增该用户: " <<  id.Addr();
        _online_user.push_back(std::make_shared<User>(id));
        PrintUser();
    }
    void DelUser(InetAddr &id)  
    {
        LockGuard lck(_mutex);
        auto pos = std::remove_if(_online_user.begin(),_online_user.end(),[&id](std::shared_ptr<UserInterface> &user){
            return *user == id;
        });
        //它用于从容器中移除满足特定条件的元素。remove_if 的工作方式是将不满足条件的元素移动到容器的前面，并返回一个指向“新末尾”的迭代器
        _online_user.erase(pos, _online_user.end());
        PrintUser();
    }
    void Router(int sockfd,const std::string& message) 
    {
        LockGuard lck(_mutex);
        for(auto e : _online_user)
        {
            LOG(LogLevel::DEBUG) << "message : " << message;
            e->SendTo(sockfd,message);
        }
    }
    void PrintUser()
    {
        for(auto user : _online_user)
        {
            LOG(LogLevel::DEBUG) <<"在线用户-> "<<  user->Id();
        }
    }
    ~UserManage(){}
private:
    std::list<std::shared_ptr<UserInterface>> _online_user;
    Mutex _mutex;
};